<!--
 * @Description:  具体使用方式请参考同文件夹下 VueComponent 和 VuePlugIn 文件           
 * @Version: 1.0
 * @Autor: chen_yt
 * @Date: 2020-11-02 17:15:31
 * @LastEditors: chen_yt
 * @LastEditTime: 2022-04-13 16:52:55
-->
<template>
  <component
    :is="connectType"
    v-if="startConnection"
    ref="connectImpl"
    :is-fks-server="isFksServer"
    :name="name"
    :url="url"
    :destination="destination"
    :connect-type="connectType"
    :connect-pending-time="connectPendingTime"
    :re-connect-interval="reConnectInterval"
    :max-reconnect="maxReconnect"
    :client-in-pool.sync="clientInPool"
    @onNewMessage="onNewMessageHandle(arguments)"
    @onSuccess="onSuccessHandle(arguments)"
    @onError="onErrorHandle(arguments)"
    @onClose="onCloseHandle(arguments)"
    @createClient="createClientInWebSocketPool"
    @updateClient="updateClientInWebSocketPool"
    @closeClient="closeClientInWebSocketPool"
  />
</template>


<script>
import store from '@/store'
import Stomp from './MultiConnect/Stomp'
import Smqtt from './MultiConnect/Smqtt'
import { getCurrentUserInfo } from '@/api/user'
import debounce from 'throttle-debounce/debounce'
// import OriginWebsocket from './MultiConnect/OriginWebsocket'

export default {
  name: 'BaseConnect',
  components: { Stomp, Smqtt },
  // mixins: [Stomp, Smqtt, OriginWebsocket],
  data() {
    return {
      onOpen: null,
      onClose: null,
      onSuccess: null,
      onError: null,
      onNewMessage: null,
      startConnection: false,
      checkToken: null
    }
  },
  computed: {
    portalId() {
      return store.state.portal.id
    },
    userName() {
      return store.state.user.userName
    },
    clientInPool() {
      return store.getters.websocketInPool(this.name)
    },
    currentClient() {
      return this.$refs.connectImpl.currentClient
    },
    sendMessage() {
      return this.$refs.connectImpl.sendMessage
    }
  },
  mounted() {
    this.checkToken = debounce(1000, this.getCurrentUserInfo)

    this.initConnect()
  },
  methods: {
    /**
     * @description:建立链接的入口，当未给链接命名时拒绝链接
     *
     */
    initConnect() {
      if (!this.url || this.url == '') {
        this.onErrorHandle('url不能为空')
        return
      }

      if (this.name == '') {
        this.onErrorHandle('链接名不能为空')
        return
      }

      //唯一性检测，池子里已有同名链接时不允许创建
      //容易出并发问题，可以把这段检测注释了
      if (this.clientInPool.name) {
        this.onErrorHandle('同名链接已存在')
        return
      }

      this.startConnection = true
    },

    /**
     * @description: 收到新消息向外抛出
     */
    onNewMessageHandle(response) {
      console.log(`new message from ${this.connectType}-${this.name}:`)
      console.dir(response)

      this.$emit('onNewMessage', response)

      if (typeof this.onNewMessage == 'function') {
        this.onNewMessage(response)
      }
    },

    /**
     * @description:  抛出链接建立成功消息
     *                链接建立后，若是stomp和smqtt会去订阅
     */
    onSuccessHandle() {
      console.log(`success connect：${this.connectType}-${this.name}`)

      this.$emit('onSuccess')

      if (typeof this.onSuccess == 'function') {
        this.onSuccess()
      }
    },

    /**
     * @description:  抛出链接建立失败消息
     *                链接建立后，stomp和ws需要手动调用重连
     */
    onErrorHandle(e = '') {
      console.log(`error connect：${this.connectType}-${this.name}`)

      // if (e) console.log(e)

      // console.dir(this.currentClient)

      this.$emit('onError', e)

      if (typeof this.onError == 'function') {
        this.onError(e)
      }

      //错误后判断token
      if (this.isFksServer) {
        this.checkToken()
      }
    },

    onCloseHandle() {
      console.log(`close connect：${this.connectType}-${this.name}`)

      this.$emit('onClose')

      if (typeof this.onClose == 'function') {
        this.onClose()
      }
    },

    /**
     * @description: 更新vuex的连接池中的对象的状态
     */
    createClientInWebSocketPool() {
      store.commit('CREATE_WEBSOCKET_POOL_CLIENT', this.currentClient)
    },

    /**
     * @description: 更新vuex的连接池中的对象的状态
     */
    updateClientInWebSocketPool() {
      store.commit('UPDATE_WEBSOCKET_POOL_CLIENT', this.currentClient)
    },

    /**
     * @description: 从vuex的连接池中删除名称对应的对象
     */
    closeClientInWebSocketPool() {
      store.commit('DEL_WEBSOCKET_POOL_CLIENT', this.name) //该方法会使链接主动关闭
    },
    getUserInfo() {
      return getCurrentUserInfo({
        userName: this.userName,
        portalId: this.portalId
      })
        .then((res) => {
          if (!res.status) {
            this.closeClientInWebSocketPool()
          }
        })
        .catch((e) => {
          this.closeClientInWebSocketPool()
        })
    }
  }
}
</script>

